/*
 * @Author            : cxh
 * @Date              : 2021-05-04 02:15:21
 * @LastEditTime      : 2021-05-04 04:25:36
 * @LastEditors       : cxh
 * @Description       : 
 * @FilePath          : /RDA/main.c
 * @copyright         : (c) 2021 AiLF. All rights reserved.
 */
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>   
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>   

int g_exit = 0;
struct UDPAddr{
    char *ip;
    int port; 
};
struct UDPAddr* clientList[100] = {0}; //最多处理100客户端
/**
 接收客户端的询问，并立即回复，用于客户端确定RDA_Monitor是不是在执行。
*/
#define BUFF_LEN 4096
#define SERVER_PORT 14080

int server_fd;
pthread_t HeartBeatThread = 0;
void *HeartBeatTask(void* arg){
    printf("HeartBeat Start\r\n");
    int ret;
    struct sockaddr_in ser_addr;

    server_fd = socket(AF_INET, SOCK_DGRAM, 0); //AF_INET:IPV4;SOCK_DGRAM:UDP
    int opt = 1;
    setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof( opt ));
    if(server_fd < 0)
    {
        printf("create socket fail!\n");
        return NULL;
    }

    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址，需要进行网络序转换，INADDR_ANY：本地地址
    ser_addr.sin_port = htons(SERVER_PORT);  //端口号，需要网络序转换

    ret = bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
    if(ret < 0)
    {
        printf("socket bind fail!\n");
        return NULL;
    }


    char buf[BUFF_LEN];  //接收缓冲区，4096字节
    int count;
    socklen_t len = sizeof(struct sockaddr_in);
    struct sockaddr_in clent_addr;  //clent_addr用于记录发送方的地址信息
    while(!g_exit)
    {
        memset(buf, 0, BUFF_LEN);
        //bezro(buf, BUFF_LEN);
        count = recvfrom(server_fd, buf, BUFF_LEN, 0, (struct sockaddr*)&clent_addr, &len);  //recvfrom是拥塞函数，没有数据就一直拥塞
        if(count != -1)
        {
	        //printf("rec Heart beat %d\r\n",count);
            sprintf(buf, "RDA_Monitor");
            buf[11] ='\0'; 
            sendto(server_fd, buf, 12, 0, (struct sockaddr*)&clent_addr, len);  //发送信息给client，注意使用了clent_addr结构体指针
            //perror("send error:");
        }else{
            // perror("rec error:");
        }
    }

    if(server_fd !=0){
        close(server_fd);
        server_fd =0;
    }
    return NULL;


}


//stat awk.txt | grep -i Modify | awk -F. '{print $1}' | awk '{print $2$3}'| awk -F- '{print $1$2$3}' | awk -F: '{print $1$2$3}'
//stat xx | grep -i Modify | awk -F. '{print $1}' | awk '{print $2}'| awk -F- '{print $1$2$3}'
pthread_t FileCheckThread = 0;
uint64_t ModifyTime = 0;
void *FileCheckTask(void* arg){
    struct timespec ts = {30,0}; //30秒 查询一次
    printf("FileCkeck Start\r\n");
    static int already_network_init = 0;
    int locacSocket;  
    if (already_network_init == 0)
    {
        already_network_init = 1;
        
        if((locacSocket = socket(AF_INET,SOCK_DGRAM,0))<0){  
            perror("socket");  
            exit(1);  
        } 
    }
    // 获取当前时间作为初始时间
    time_t _t;
    time(&_t); 
    struct tm *_tm_m = gmtime(&_t);
    ModifyTime = (_tm_m->tm_year+1900)*10000000000 + (_tm_m->tm_mon+1)*100000000 +  (_tm_m->tm_mday)*1000000
              +  (_tm_m->tm_hour)*10000 +  (_tm_m->tm_min)*100 + (_tm_m->tm_sec);
    printf("initial time %llu\r\n",ModifyTime);

    do
    {
        
        time_t t;
        time(&t); 
        struct tm *tm_m = gmtime(&t); //gmtime 返回UTC Time; localtime()返回本地时间

        // char fileName[128] ={0};
        // sprintf(fileName,"/opt/rda/log/%4d%02d%02d_Alarm.log",tm_m->tm_year+1900, tm_m->tm_mon+1, tm_m->tm_mday);
        char *fileName = "/home/rda/Monitor/test.c";
        char cmdStr[256] ={0};
        sprintf(cmdStr,"stat %s | grep -i Modify | awk -F. '{print $1}' | awk '{print $2$3}'| awk -F- '{print $1$2$3}' | awk -F: '{print $1$2$3}'",fileName);

        char lineBuf[256] = {0};
        FILE * fp = popen(cmdStr, "r");
        if (fp == NULL) {
            goto sleep;
        }

        char *rett  = fgets(lineBuf, sizeof(lineBuf), fp);
        if (rett != NULL){ 
            // 如果没文件返回 stat: xxxx: stat: No such file or directory
            // 否则返回 20210503120001字符串
            uint64_t _modifyTime = strtoull(rett,NULL,10);
            //printf("modify %llu\r\n",_modifyTime);
            if(_modifyTime > ModifyTime){ //新的报警
                ModifyTime =  _modifyTime;
                // 找到文件最后一行
                FILE *_fp = fopen(fileName,"r");
                if(_fp ==NULL){
                     goto sleep;
                }
                char alarmLine[512] = {0};
                do{
                     char* _rettt = fgets(alarmLine,512,_fp);
                     if(_rettt ==NULL){
                         break;
                     }
                }while (1);
                fclose(_fp);
                printf("%s",alarmLine);


                int index =0;
                do{
                    struct UDPAddr* _addr = clientList[index ++];
                    if(_addr == NULL || index >=100){
                        break;
                    }
                    struct sockaddr_in scoketAddr;  
                    int addr_len =sizeof(struct sockaddr_in); 
                    bzero(&scoketAddr,sizeof(scoketAddr));  
                    scoketAddr.sin_family = AF_INET;  
                    scoketAddr.sin_port = htons(_addr->port);  
                    scoketAddr.sin_addr.s_addr = inet_addr(_addr->ip);

                    sendto(locacSocket, alarmLine, strlen(alarmLine)+1,0,(struct sockaddr *)&scoketAddr,addr_len);
                }while (1);
            }
        }
        
        pclose(fp);
sleep:
    nanosleep(&ts, NULL); //休眠30秒

    }while (!g_exit);

    return NULL;
}

void IntHandl(int i)
{   
    g_exit = 1;
    if(server_fd !=0){
        close(server_fd);
        server_fd =0;
    }
     
}

int main(void){
    signal(SIGINT, IntHandl);
    g_exit =0;
    
    // 读配置配置文件 clientList.ini
   //FILE *fp = fopen("./clientList.ini","r");
    //if (fp ==NULL)
    //{
        // 添加第一个IP
		
        clientList[0] = (struct UDPAddr*)malloc(sizeof(struct UDPAddr));
        clientList[0]->ip = "10.78.136.111";
        clientList[0]->port =14080;
		
        clientList[1] = (struct UDPAddr*)malloc(sizeof(struct UDPAddr));
        clientList[1]->ip = "10.78.133.26";
        clientList[1]->port =14080;
		
        //添加第三个IP
        //clientList[3] = ((struct UDPAddr)*)malloc(sizeof(struct UDPAddr));
        //clientList[3]->ip = "10.78.XXX.XXX";
        //clientList[3]->port =14080;
        //可以继续添加第三个IP，最多添加100个


    //}
    //else
    //{
    //    // todo read file to array
    // //   fclose(fp);
    //}

 
    printf("Start\r\n");
    pthread_create(&HeartBeatThread, NULL, HeartBeatTask, NULL);
    pthread_create(&FileCheckThread, NULL, FileCheckTask, NULL);

    while (!g_exit);
    pthread_join(HeartBeatThread,NULL);
    pthread_join(FileCheckThread,NULL);
    printf("Stop\r\n");
    return 0;
}
